/**
 * 权限声明：
 */
package com.handy.webwork.action;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.LinkedList;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.handy.webwork.action.result.Default;
import com.handy.webwork.action.result.Forward;
import com.handy.webwork.action.result.FreeMarker;
import com.handy.webwork.action.result.Redirect;
import com.handy.webwork.action.result.StaticFile;
import com.handy.webwork.config.HandyConfiguration;

/**
 * 执行拦截器与控制器。
 * 
 * @author rocken.zeng@gmail.com
 * 
 */
public class InvokService {
	private static Log log = LogFactory.getLog(InvokService.class);

	private HttpServletRequest request;

	private HttpServletResponse response;

	private ServletContext context;
	
	private ActionMapping actionMapping;

	public InvokService(HttpServletRequest request,
			HttpServletResponse response, ServletContext context) {
		this.request = request;
		this.response = response;
		this.context = context;
	}

	/**
	 * 处理用户正确的请求。
	 * 
	 * @param request
	 * @param response
	 * @param context
	 * @param actionMapping
	 * @throws IOException
	 * @throws ServletException
	 */
	@SuppressWarnings("unchecked")
	public void invok(ActionMapping actionMapping) throws IOException,
			ServletException {
		this.actionMapping = actionMapping;
		// 处理form参数====================================
		// 生成form
		final ActionForm actionForm = new ActionForm(request, context);
		// 框架接收form时所产生成错误写入ActionMessage(主要异常:上传文件时是否有错误)
		final ActionMessage actionMessage = actionForm.validate();


		ActionResult result = null;
		if (log.isDebugEnabled()) {
			log.debug("auto validate form...");
			log.debug("actionMessage.size()=" + actionMessage.size());
			log.debug("actionMessage.isEmpty()=" + actionMessage.isEmpty());
		}

		//form自动验证失败的情况下，跳转到input页面。
		if (!actionMessage.isEmpty()) {
			result = actionMapping.getActionResults().get("INPUT");// 验证表单出错，跳转到input页面。

			if (null == result) {// 未找到ActionResult,放弃。
				//log.error("auto validate form , can not find INPUT result");
				log.error("auto validate form , can not find INPUT result");
				return;
			}

			if (result.getResultType().equalsIgnoreCase(
					HandyConfiguration.RESULT_FREEMARKER)) {// freemarker
				new FreeMarker(request, response, context).doFreeMarker(actionMapping,
						new Action() {
							public HashMap sendData() {
								HashMap root = new HashMap();
								// 参数传递给页面
								root.putAll(actionForm.getFormMap());//form共享
								root.putAll(actionMessage.getMessage());
								return root;
							}
						}, result.getContentType(),result.getResultValue());
			} else if (null == result.getResultType()
					|| result.getResultType().equals("")) {
				String url = result.getResultValue();
				if (!url.startsWith("/")) {
					url = "/" + url.trim();
				}
				RequestDispatcher rd = context.getRequestDispatcher(url);
				rd.forward(request, response);
			}
		}
		// ================================处理form参数结束

		// 将拦截器与该次请求的控制器组成管道让用户请求通过。
		LinkedList<ActionMapping> actionMappings = new LinkedList<ActionMapping>();
		if (HandyConfiguration.interceptorMappings(
				actionMapping.getActionPackage()) != null) {
			actionMappings.addAll(HandyConfiguration.interceptorMappings(
					actionMapping.getActionPackage()));// 控制器所在包的所有拦截器
		}
		actionMappings.add(actionMapping);
		if (log.isDebugEnabled()) {
			for (ActionMapping mapping : actionMappings) {
				log.info(mapping.getActionName());
			}
		}
		doAction(actionMappings, actionForm);

	}

	/**
	 * 执行拦截器和控制器，返回处理结果。
	 * 
	 * @param actionMappings
	 *            该链表应该为多个拦截器与一个控制器（或转向器）的组合
	 * @throws IOException
	 * @throws ServletException
	 */
	@SuppressWarnings("unchecked")
	private void doAction(LinkedList<ActionMapping> actionMappings,ActionForm actionForm) {
		if (log.isDebugEnabled()){
			log.debug("doAction()");
		}
		ActionMessage actionMessage = new ActionMessage();
		HashMap map = new HashMap();
		//map.put("actionMapping", actionMapping);//将本次用户请求的action信息注入到管道中所有action中(如果该action中定义了actionMapping变量)
		String actionName = "";
		if (log.isDebugEnabled()){
			log.debug("该管道的action数量为： = " + actionMappings.size());
		}
		for (ActionMapping _actionMapping : actionMappings) {
			AbstractAction action = null;
			ActionResult result = null;
			actionName = _actionMapping.getActionName();
			if (log.isDebugEnabled()){
				log.debug("actionName = " + actionName);
			}
			// 生成action类实例
			if (_actionMapping.getStyle() == HandyConfiguration.ACTION_SYTLE_FORWARD) {
				if (log.isDebugEnabled()){
					log.debug("该action的类型为 <FORWARD> ,直接返回'success'到页面显示。");
				}
				action = new Action() {
					public String execute() {
						return "SUCCESS";
					}
					public HashMap sendData() {//参数处理
						HashMap root = super.sendData();
						root.put("form", this.form);//将form传给FORWARD
						return root;
					}
					public void getForm(ActionForm form) {
						this.form = form;
					}
					
					private ActionForm form;
					
				};
			} else {
				if (log.isDebugEnabled()){
					log.debug("该action的类型为 非<FORWARD> ,actionClass="+_actionMapping.getActionClass());
				}
				// 生成控制器处理类
				try {
					Class<AbstractAction> c = (Class<AbstractAction>) Class
							.forName(_actionMapping.getActionClass());
					action = c.newInstance();
					action.setActionMapping(this.actionMapping);
				} catch (ClassNotFoundException e) {
					log.error(e.getMessage());
				} catch (InstantiationException e) {
					log.error(e.getMessage());
				} catch (IllegalAccessException e) {
					log.error(e.getMessage());
				}
				if (log.isDebugEnabled()) {
					log.info(_actionMapping.getActionClass() + "实例生成完毕");
				}

				if (null == action) {
					log.error("can not find " + _actionMapping.getActionClass());
					return;
				}
			}

			// 将session装载到action中
			action.setSession(request.getSession());
			if (log.isDebugEnabled()){
				log.debug("将session传送到action中");
			}
			// 将request装载到action中
			action.setRequest(request);
			if (log.isDebugEnabled()){
				log.debug("将request传送到action中");
			}
			
			action.setResponse(response);
			if (log.isDebugEnabled()){
				log.debug("将response传送到action中");
			}
			
			action.setContext(context);
			if (log.isDebugEnabled()){
				log.debug("将context传送到action中");
			}
			
			// 将map中的值填充到action中
			if (map != null && !map.isEmpty()) {
//				Set<Entry<String, String>> _params = map.entrySet();
//				for (Map.Entry<String, String> entry : _params) {
//					try {
//						BeanUtils.setProperty(action, entry.getKey(), entry
//								.getValue());
//					} catch (IllegalAccessException e) {
//						log.error(e.getMessage());
//					} catch (InvocationTargetException e) {
//						log.error(e.getMessage());
//					}
//				}
				try {
					// 使用一个map为bean赋值
					BeanUtils.populate(action, map);//自动装载form值到action中
				} catch (IllegalAccessException e) {
					log.error(e.getMessage());
				} catch (InvocationTargetException e) {
					log.error(e.getMessage());
				}
			}
			
			// 处理form,将form装载到action中。
			if (HandyConfiguration.autoHandleParam()) {// 自动将form中的数据装载到action中。
				if (log.isDebugEnabled()) {
					log.debug("自动将form中的数据装载到action中");
				}
				try {
					// 使用一个map为bean赋值
					BeanUtils.populate(action, actionForm.getFormMap());//自动装载form值到action中
				} catch (IllegalAccessException e) {
					log.error(e.getMessage());
				} catch (InvocationTargetException e) {
					log.error(e.getMessage());
				}
			} else {
				if (log.isDebugEnabled()){
					log.debug("将form传送到action中。");
				}
				action.getForm(actionForm);//仅仅把ActionForm传给action,由action执行actionForm.get...()方法获取from里的具体值
			}
			// 处理form完
			
			if (log.isDebugEnabled()){
				log.debug("开始执行action.execute()方法。");
			}
			// 执行action,取返回值。
			String resultString = action.execute();
			
			if (resultString ==null || "".equals(resultString)){
				log.error("请检查action["+_actionMapping.getActionClass()+"]执行execute()后的返回值，该值不能为空。");
				return;
			}
			
			// 处理特殊的resultString
			// 当返回的是一个静态文件时
			if (AbstractAction.HANDY_STATIC_FILE.equalsIgnoreCase(resultString)) {
				new StaticFile(request, response, context).doStaticFile(action);
				return;
			} else if (AbstractAction.HANDY_ACTION_RESPONSE
					.equalsIgnoreCase(resultString)) {
				return;
			} else if (AbstractAction.HANDY_DYNA_FTL
					.equalsIgnoreCase(resultString)) {
				new FreeMarker(request, response, context).doFreeMarker(_actionMapping,action,"","");
				return;
			} 
			//--处理特殊的resultString结束
			
			if (_actionMapping.getStyle() == HandyConfiguration.ACTION_SYTLE_ACTION) {
				// 执行action.validate(自定义执行验证)
				actionMessage = action.validate(actionMessage);// 拦截器返回的一定是空值。
				if (null == actionMessage || actionMessage.isEmpty()) {
					// 执行action.execute得到运行结果，做相应处理。
					result = _actionMapping.getActionResults().get(
							resultString.toUpperCase());
				} else {
					result = _actionMapping.getActionResults().get("INPUT");
				}
			} else if (_actionMapping.getStyle() == HandyConfiguration.ACTION_SYTLE_INTERCEPTOR) {
				if (resultString.equalsIgnoreCase("success")) {
					// 拦截器返回success才进入下一个拦截器或最终控制器。
					try {
						map.putAll(PropertyUtils.describe(action));
					} catch (IllegalAccessException e) {
						log.error(e.getMessage());
					} catch (InvocationTargetException e) {
						log.error(e.getMessage());
					} catch (NoSuchMethodException e) {
						log.error(e.getMessage());
					}
					continue;// 拦截器返回success,运行下一个action
				}
				result = _actionMapping.getActionResults().get(
						resultString.toUpperCase());//该result由拦截器提供
			} else if (_actionMapping.getStyle() == HandyConfiguration.ACTION_SYTLE_FORWARD) {
				result = _actionMapping.getActionResults().get(
						resultString.toUpperCase());
			}

			if (null == result) {// 未找到ActionResult,放弃。
				log.error("\""+actionName+"\"中没有定义名为<"+resultString+">的result");
				//log.error("can not find result<"+resultString+"> in "+ actionName +" Action");
				break;
			}
			if (result.getResultValue() == null
					|| result.getResultValue().equals("")) {
				log.error("\""+actionName+"\"中名为<"+resultString+">的result没有值");
				//log.error("result<"+resultString+"> in "+ actionName +" Action value is null");
				break;
			}
			if (log.isDebugEnabled()) {
				log.info("action result type :");
				log.info(result.getResultType());
			}

			if (result.getResultType() == null
					|| result.getResultType().equals("")) {
				//当没有指定result类型时让容器处理视图。
				new Default(request, response, context).doDefault(_actionMapping,action,
						result.getResultValue());
				break;
			} else if (result.getResultType().equalsIgnoreCase(
					HandyConfiguration.RESULT_FREEMARKER)) {// freemarker
				new FreeMarker(request, response, context).doFreeMarker(_actionMapping,action,
						result.getContentType(),result.getResultValue());
				break;
			} else if (result.getResultType().equalsIgnoreCase(
					HandyConfiguration.RESULT_FORWARD)) {// forward
				new Forward(request, response, context).doForward(action,
						result, actionForm, actionMessage);
				break;
			} else if (result.getResultType().equalsIgnoreCase(
					HandyConfiguration.RESULT_REDIRECT)) {// redirect
				new Redirect(request, response).doRedirect(action, result
						.getResultValue());
				break;
			}
		}

	}
}